***************************************************************************/ { iicTfr.nrMessages = 2; iicTfr.p_message = p_iicMsg; p_iicMsg[0] = msg1; p_iicMsg[1] = msg2; StartTransfer(); }
23
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
APPENDIX II
I2CMASTR.C
/***************************************************************************/ /* Acronym : IC Inter IC bus (for P90CL301) */ /* Name of module : I2CMASTR.C */ /* Scope : Universal IC driver */ /* 12nc : xxxx xxx xxxx.x */ /* Creation date : 1994-08-08 */ /* Program language : C */ /* Name : P.H. Seerden */ /* */ /* */ /* (C) Copyright 1994 Philips Semiconductors B.V. */ /* Product Concept & Application Laboratory Eindhoven (PCALE) */ /* Eindhoven - The Netherlands */ /* */ /* All rights are reserved. Reproduction in whole or in part is */ /* prohibited without the written consent of the copyright owner. */ /* */ /***************************************************************************/ /* */ /* Description: */ /* */ /* Driver for the IC hardware interface on the Philips P90CL301 */ /* microcontroller. */ /* */ /* Part of the driver that handles master bus-transfers. */ /* Everything between a Start and Stop condition is called a TRANSFER. */ /* One transfer consists of one or more MESSAGEs. */ /* To start a transfer call function "I2C_Transfer". */ /* */ /***************************************************************************/ /* */ /* History: */ /* */ /* 94-08-08 P.H. Seerden Initial version */ /* */ /* */ /***************************************************************************/ #include "i2cexprt.h" #include "i2cdrivr.h" #include "reg90301.h"
extern void (*masterProc)(); static I2C_TRANSFER *tfr; static I2C_MESSAGE *msg; /* Ptr to active transfer block /* ptr to active message block */ */ */ */ */
static void (*readyProc)(BYTE,BYTE); /* proc. to call if transfer ended static BYTE msgCount; /* Number of messages to sent static BYTE dataCount; /* bytes send/received of current message
24
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
static void HandleMasterState(void) /********************************** * Input(s) : none. * Output(s) : none. * Returns : none. * Description : Master mode state handler for I2C bus. ***************************************************************************/ { switch(SSTA >> 3) /* >> 3 for faster code */ { /* 00 */case 0 : /* Bus Error has occurred */ SCON = GENERATE_STOP; /* release bus, clr STA and SI */ break; /* 08 */case 1 : /* (repeated) Start condition has been transmitted */ /* 10 */case 2 : /* Slave address + R/W are transmitted */ SDAT = msg->address; SCON = RELEASE_BUS_ACK; /* clr STO, STA, SI and set AA */ break; /* 18 */case 3 : /* SLA+W or DATA transmitted, ACK received */ /* 28 */case 5 : /* DATA or STOP will be transmitted */ if (dataCount < msg->nrBytes) { SDAT = msg->buf[dataCount++]; /* sent first byte */ SCON = RELEASE_BUS_ACK; /* clr STA, SI */ } else { if (msgCount < tfr->nrMessages) { dataCount = 0; msg = tfr->p_message[msgCount++]; /* next message */ SCON = RELEASE_BUS_STA; /* generate (rep)START */ } else { SCON = GENERATE_STOP; readyProc(I2C_OK, msgCount); } } break; /* 20 */case 4 : /* 48 */case 9 : /* SLA+W/R transmitted, NOT ACK received */ readyProc(I2C_NACK_ON_ADDRESS, msgCount); /* driver finished */ SCON = GENERATE_STOP; break; /* 30 */case 6 : /* DATA transmitted, NOT ACK received */ readyProc(I2C_NACK_ON_DATA, msgCount); SCON = GENERATE_STOP; break; /* 38 */case 7 : /* Arbitration lost in SLA+W or DATA */ SCON = RELEASE_BUS_STA; /* release bus, set STA */ break; /* 40 */case 8 : /* SLA+R transmitted, ACK received */ if (msg->nrBytes == 1) SCON = RELEASE_BUS_NOACK; /* No ack on next byte */ else SCON = RELEASE_BUS_ACK; /* ACK on next byte */ break; /* 50 */case 10 : /* DATA received, ACK has been returned */ msg->buf[dataCount++] = SDAT; /* read next data */ if (dataCount + 1 == msg->nrBytes) /* next byte the last ? SCON = RELEASE_BUS_NOACK; /* No ack on next byte else SCON = RELEASE_BUS_ACK; /* return ACK break; /* 58 */case 11 : /* DATA received, NOT ACK has been returned msg->buf[dataCount] = SDAT; /* read last data if (msgCount < tfr->nrMessages) { dataCount = 0; msg = tfr->p_message[msgCount++]; /* next message SCON = RELEASE_BUS_STA; /* generate (rep)START } else { SCON = GENERATE_STOP; readyProc(I2C_OK, msgCount); } } } */ */ */ */ */
*/ */
25
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
void I2C_InitializeMaster(void) /****************************** * Input(s) : None. * Output(s) : None. * Returns : None. * Description : Enable IC bus and set the clock speed for IC. ***************************************************************************/ { masterProc = HandleMasterState; PCON |= 0x0C; SADR = 0x26; SCON = RELEASE_BUS_ACK; } void I2C_Transfer(I2C_TRANSFER *p, void (*proc)(BYTE, BYTE)) /*********************************************************** * Input(s) :p address of IC transfer parameter block. * proc procedure to call when transfer completed, * with the driver status and the nr of mesgs * passed as parameters. * Output(s) : None. * Returns : None. * Description: Start an IC transfer, containing 1 or more messages. The * application must leave the transfer parameter block * untouched until the ready procedure is called. * The first IC message is started with sending a start * condition followed by the slave address. ***************************************************************************/ { tfr = p; readyProc = proc; msgCount = 0; dataCount = 0; msg = tfr->p_message[msgCount++]; /* first message to send */ SCON = RELEASE_BUS_STA; } /* generate START condition */ /* set alternate I/O port function to IC /* set default slave address /* set speed and enable IC hardware */ */ */
26
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
APPENDIX III I2CSLAVE.C
/***************************************************************************/ /* Acronym : IC Inter IC bus (for P90CL301) */ /* Name of module : I2CSLAVE.C */ /* Scope : Universal IC driver */ /* 12nc : xxxx xxx xxxx.x */ /* Creation date : 1994-08-08 */ /* Program language : C */ /* Name : P.H. Seerden */ /* */ /* */ /* (C) Copyright 1994 Philips Semiconductors B.V. */ /* Product Concept & Application Laboratory Eindhoven (PCALE) */ /* Eindhoven - The Netherlands */ /* */ /* All rights are reserved. Reproduction in whole or in part is */ /* prohibited without the written consent of the copyright owner. */ /* */ /***************************************************************************/ /* */ /* Description: */ /* */ /* Driver for the IC hardware interface on the Philips P90CL301 */ /* microcontroller. */ /* */ /* Part of the driver that handles slave bus-transfers. */ /* */ /***************************************************************************/ /* */ /* History: */ /* */ /* 94-08-08 P.H. Seerden Initial version */ /* */ /* */ /***************************************************************************/ #include "i2cexprt.h" #include "i2cdrivr.h" #include "reg90301.h"
extern void (*slaveProc)(); static static static static BYTE BYTE BYTE BYTE count; *slaveBuf; size; slaveStatus; /* /* /* /* bytes send/received of current message ptr to rec/trm data into/from if slave size of slave mode buffer status of the slave */ */ */ */
27
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
void HandleSlaveState(void) /************************** * Input(s) : none. * Output(s) : none. * Returns : none. * Description : State handler for I2C. ***************************************************************************/ { switch(SSTA >> 3) /* >> 3 for faster code */ { /* 60 */case 12 : /* 68 */case 13 : /* Addressed as slave */ /* 70 */case 14 : /* 78 */case 15 : slaveStatus = SLAVE_BUSY; count = 0; if (size > 1) SCON = RELEASE_BUS_ACK; /* return ACK on first byte */ else SCON = RELEASE_BUS_NOACK; /* return NACK on first byte */ break; /* 80 */case 16 : /* 90 */case 18 : /* Data received, ACK returned */ slaveBuf[count++] = SDAT; /* read data */ if (count == size) SCON = RELEASE_BUS_NOACK; /* return NACK on next byte */ else SCON = RELEASE_BUS_ACK; /* return ACK on next byte */ break; /* 88 */case 17 : /* 98 */case 19 : /* data byte received, NACK returned */ slaveStatus = SLAVE_RCV_ERROR; SCON = RELEASE_BUS_ACK; /* clr SI, set AA */ break; /* A0 */case 20 : /* STOP or REP.START received, while addressed as slave */ slaveStatus = SLAVE_READY; SCON = RELEASE_BUS_ACK; /* clr SI, set AA */ break; /* B0 */case 22 : /* Arb. lost as MST, addressed as slave transmitter */ slaveStatus = SLAVE_BUSY; count = 0; SDAT = slaveBuf[count++]; /* Transmit next data, restart */ SCON = RELEASE_BUS_STA; /* MST mode if bus is free again */ break; /* A8 */case 21 : /* Addressed as slave transmitter */ slaveStatus = SLAVE_BUSY; count = 0; /* B8 */case 23 : /* Data transmitted, ACK received */ SDAT = slaveBuf[count++]; /* Transmit next data */ SCON = RELEASE_BUS_ACK; /* clr SI, set AA */ break; /* C0 */case 24 : /* Data transmitted, NOT ACK received */ slaveStatus = SLAVE_TRX_ERROR; /* C8 */case 25 : SCON = RELEASE_BUS_ACK; /* clr SI, set AA */ break; } }
28
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
void I2C_InitializeSlave(BYTE slv, BYTE *buf, BYTE size) /******************************************************* * Input(s) : slv Own slave address * buf Pointer to slave data buffer * size size of the slave data buffer * Output(s) : None. * Returns : None. * Description : Enable IC (slave) bus and set the clock speed for IC. ***************************************************************************/ { slaveProc = HandleSlaveState; slaveStatus = SLAVE_IDLE; slaveBuf = buf; size = size; PCON |= 0x0C; SADR = slv; SCON = RELEASE_BUS_ACK; } void I2C_ProcessSlave(void) /************************** * Input(s) : None. * Output(s) : None. * Returns : None. * Description: Process the slave. * This function must be called by the application to check * the slave status. The USER should adapt this function to * his personal needs (take the right action at a certain * status). ***************************************************************************/ { switch(slaveStatus) { case SLAVE_IDLE : /* do nothing or fill transmit buffer for transfer */ break; case SLAVE_BUSY : /* do nothing if interrupt driven, else poll SCON.SI bit */ if ((PICR3 & 0x70) == 0) /* level 0 -> polling */ { if (SCON & 0x08) /* wait until SI bit is set */ MainStateHandler(); } break; case SLAVE_READY : /* read or fill buffer for next transfer, signal application */ slaveStatus = SLAVE_IDLE; break; case SLAVE_TRX_ERROR : /* generate error message */ slaveStatus = SLAVE_IDLE; break; case SLAVE_RCV_ERROR : /* generate error message */ slaveStatus = SLAVE_IDLE; break; } }
/* set alternate I/O port function to IC /* own slave address /* set speed and enable IC hardware
*/ */ */
29
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
APPENDIX IV
I2CDRIVR.C
/***************************************************************************/ /* Acronym : IC Inter IC bus (for P90CL301) */ /* Name of module : I2CDRIVR.C */ /* Scope : Universal IC driver */ /* 12nc : xxxx xxx xxxx.x */ /* Creation date : 1994-08-08 */ /* Program language : C */ /* Name : P.H. Seerden */ /* */ /* */ /* (C) Copyright 1994 Philips Semiconductors B.V. */ /* Product Concept & Application Laboratory Eindhoven (PCALE) */ /* Eindhoven - The Netherlands */ /* */ /* All rights are reserved. Reproduction in whole or in part is */ /* prohibited without the written consent of the copyright owner. */ /* */ /***************************************************************************/ /* */ /* Description: */ /* */ /* Driver for the IC hardware interface on the Philips P90CL301 */ /* microcontroller. */ /* */ /* Main part of the driver. */ /* Contains the interrupt handler and does calls to the master */ /* and/or slave driver part. */ /* */ /***************************************************************************/ /* */ /* History: */ /* */ /* 94-08-08 P.H. Seerden Initial version */ /* */ /* */ /***************************************************************************/ #include "i2cexprt.h" #include "i2cdrivr.h" #include "reg90301.h"
void (*masterProc)() = NoInitErrorProc; void (*slaveProc)() = NoInitErrorProc;
static void NoInitErrorProc(void) /******************************** * Input(s) : none. * Output(s) : none. * Returns : none. * Description : ERROR: Master or slave handler called while not initialized ***************************************************************************/ { SCON = RELEASE_BUS_NOACK; /* clr STO, AA and SI */ }
30
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
void MainStateHandler(void) /************************** * Input(s) : none. * Output(s) : none. * Returns : none. * Description : Main event handler for I2C. ***************************************************************************/ { if (SSTA < 0x60) masterProc(); else slaveProc(); }
interrupt void I2C_Interrupt(void) /********************************* * Input(s) : none. * Output(s) : none. * Returns : none. * Description : Interrupt handler for I2C. * The address of this function must be loaded into one of * the on-chip autovectors. ***************************************************************************/ { MainStateHandler(); /* calls procedure to handle the current state */ }
void I2C_InstallInterrupt(BYTE intLevel) /*************************************** * Input(s) : intLevel Interrupt level (number from 0-7) * Output(s) : none. * Returns : none. * Description : Install interrupt for IC. ***************************************************************************/ { PICR3 = PICR3 | (intLevel << 4) | 0x80; }
31
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
APPENDIX V
I2CEXPRT.H
/***************************************************************************/ /* Acronym : I2C Inter IC bus */ /* Name of module : I2CEXPRT.H */ /* Scope : Application software */ /* 12nc : xxxx xxx xxxx.x */ /* Creation date : 1992-12-10 */ /* Program language : C */ /* Name : P.H. Seerden */ /* */ /* */ /* (C) Copyright 1993 Philips Semiconductors B.V. */ /* Product Concept & Application Laboratory Eindhoven (PCALE) */ /* Eindhoven - The Netherlands */ /* */ /* All rights are reserved. Reproduction in whole or in part is */ /* prohibited without the written consent of the copyright owner. */ /* */ /***************************************************************************/ /* */ /* Description: */ /* */ /* This module consists a number of exported declarations of the I2C */ /* driver package. Include this module in your source file if you want */ /* to make use of one of the interface functions of the package. */ /* */ /***************************************************************************/ /* */ /* History: */ /* */ /* 92-12-10 P.H. Seerden Initial version */ /* */ /* */ /***************************************************************************/ #define FALSE #define TRUE 0 1
/***************************************************************************/ /* EXPORTED DATA STRUCTURES */ /***************************************************************************/ #define NULL typedef unsigned char typedef unsigned short typedef unsigned long typedef struct { BYTE address; BYTE nrBytes; BYTE *buf; } I2C_MESSAGE; typedef struct { BYTE nrMessages; I2C_MESSAGE **p_message; } I2C_TRANSFER; ((void *) 0) BYTE; WORD; LONG; /* a null pointer */
/* slave address to sent/receive message /* number of bytes in message buffer /* pointer to application message buffer
*/ */ */
/* number of message in one transfer */ /* pointer to pointer to message */
32
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
/***************************************************************************/ /* EXPORTED DATA DECLARATIONS */ /***************************************************************************/ /**** Status Errors ****/ #define #define #define #define #define #define #define #define #define #define #define I2C_OK I2C_BUSY I2C_ERR I2C_NO_DATA I2C_NACK_ON_DATA I2C_NACK_ON_ADDRESS I2C_DEVICE_NOT_PRESENT I2C_ARBITRATION_LOST I2C_TIME_OUT I2C_SLAVE_ERROR I2C_INIT_ERROR 0 1 2 3 4 5 6 7 8 9 10 /* transfer ended No Errors /* transfer busy /* err: general error /* err: No data in block /* err: No ack on data /* err: No ack on address /* err: Device not present /* err: Arbitration lost /* err: Time out occurred /* err: slave mode error /* err: Initialization (not done) */ */ */ */ */ */ */ */ */ */ */
/***************************************************************************/ /* INTERFACE FUNCTION PROTOTYPES */ /***************************************************************************/ extern extern extern extern extern extern extern extern extern extern void I2C_InitializeMaster(void); void I2C_InitializeSlave(BYTE slv, BYTE *buf, BYTE size); void I2C_InstallInterrupt(BYTE intLevel); interrupt void I2C_Interrupt(void); void void void void void void I2C_Write(I2C_MESSAGE *msg); I2C_WriteRepWrite(I2C_MESSAGE *msg1, I2C_MESSAGE *msg2); I2C_WriteRepRead(I2C_MESSAGE *msg1, I2C_MESSAGE *msg2); I2C_Read(I2C_MESSAGE *msg); I2C_ReadRepRead(I2C_MESSAGE *msg1, I2C_MESSAGE *msg2); I2C_ReadRepWrite(I2C_MESSAGE *msg1, I2C_MESSAGE *msg2);
33
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
APPENDIX VII I2CDRIVR.H
/***************************************************************************/ /* Acronym : IC Inter IC bus (for P90CL301) */ /* Name of module : I2CDRIVR.H */ /* Scope : IC driver */ /* 12nc : xxxx xxx xxxx.x */ /* Creation date : 1994-22-02 */ /* Program language : C */ /* Name : P.H. Seerden */ /* */ /* */ /* (C) Copyright 1994 Philips Semiconductors B.V. */ /* Product Concept & Application Laboratory Eindhoven (PCALE) */ /* Eindhoven - The Netherlands */ /* */ /* All rights are reserved. Reproduction in whole or in part is */ /* prohibited without the written consent of the copyright owner. */ /* */ /***************************************************************************/ /* */ /* Description: */ /* */ /* This module consists of 'local' (within IC subsystem) declarations */ /* of the IC (iicdrv.c) driver. */ /* */ /***************************************************************************/ /* */ /* History: */ /* */ /* 16-08-94 P.H. Seerden Initial version */ /* */ /* */ /***************************************************************************/ #define #define #define #define #define SLAVE_IDLE SLAVE_BUSY SLAVE_READY SLAVE_TRX_ERROR SLAVE_RCV_ERROR 0 1 2 3 4
/* /* /* /*
Immediate data to write into SCON CR2-CR1-CR0 = 000 change these values and recompile module i2cdrivr.c if a different bus speed is needed GENERATE_STOP RELEASE_BUS_ACK RELEASE_BUS_NOACK RELEASE_BUS_STA 0x54 0x44 0x40 0x64
*/ */ */ */
#define #define #define #define
/*=========================================================================*/ /* LOCAL FUNCTION PROTOTYPES */ /*=========================================================================*/ static void NoInitErrorProc(void); /*=========================================================================*/ /* GLOBAL FUNCTION PROTOTYPES */ /*=========================================================================*/ extern void MainStateHandler(void); extern void I2C_Transfer(I2C_TRANSFER *p, void (*proc)(BYTE, BYTE));
34
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
APPENDIX VII REG90301.H
/***************************************************************************/ /* Acronym : GENERAL */ /* Name of module : REG90301.H */ /* 12nc : xxxx xxx xxxx.x */ /* Creation date : 1992-11-09 */ /* Program language : C */ /* Name : P.H. Seerden */ /* */ /* */ /* Copyright (C) Philips Semiconductors B.V. */ /* Product Concept & Application Laboratory Eindhoven (PCALE) */ /* Eindhoven - The Netherlands */ /* */ /* All rights are reserved. Reproduction in whole or in part is */ /* prohibited without the written consent of the copyright owner. */ /* */ /***************************************************************************/ /* */ /* Description: */ /* */ /* Hardware register (I/O port) description file of the P90CL301 */ /* 16 bit micro-controller, for use in C programs. */ /* */ /* Registers which don't contain individual bits, are defined with */ /* BYTE_AT and/or WORD_AT, the use of those registers is as follows: */ /* registers_name = value (i.e. TH=0x45;) */ /* */ /* Registers which do contain individual bits, are defined as unions. */ /* This enables you to choose between byte and bit access, the usage */ /* is as follows: */ /* register_name.reg = value (i.e. TCON.reg=0x45;) or */ /* register_name.bit.bit_name = value (i.e. SCON.bit.ti = 0;) */ /* */ /* */ /***************************************************************************/ /* */ /* History: */ /* */ /* 92-11-09 P.H. Seerden Initial version */ /* 92-12-07 J. Pijnenburg Add bit definitions */ /* 92-08-16 P.H. Seerden Modified for 90CL301 */ /* */ /***************************************************************************/ #define BYTE_AT(x) #define WORD_AT(x) #define LONG_AT(x) (*(unsigned char *)x) (*(unsigned short int *)x) (*(unsigned long int *)x)
/*-------------------------------------------------------------------------*/ /* Register Bit Definitions: SYSCON */ /*-------------------------------------------------------------------------*/ typedef union { WORD reg; struct { BYTE dummy : 5; BYTE pclk2 : 1; /* per. clock FCLK2 prescaler */ BYTE pde : 1; /* A22-19 as 8051 chip selects */ BYTE gf : 1; /* general purpose flag bit */ BYTE pclk : 2; /* per. clock FCLK prescaler */ BYTE im : 1; /* nested interrupt mode */ BYTE wd : 1; /* bus cycle watch dog time out */ BYTE fbc : 1; /* fast bus cycle */ BYTE pd : 1; /* power down mode */ BYTE idl : 1; /* idle mode */ BYTE doff : 1; /* delay counter off */ } b; } SYSCON_TYPE;
35
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
/*-------------------------------------------------------------------------*/ /* Register Bit Definitions: SCONx (Uart0 and 1) */ /*-------------------------------------------------------------------------*/ typedef union { BYTE reg; struct { BYTE SM : 3; BYTE REN : 1; BYTE TB8 : 1; BYTE RB8 : 1; BYTE TI : 1; BYTE RI : 1; } b; } SCONX_TYPE;
/*-------------------------------------------------------------------------*/ /* SYSTEM STATUS & CONTROL */ /*-------------------------------------------------------------------------*/ #define SYSCON (*(SYSCON_TYPE*) 0xFFFF8000) /* system control register */ /*-------------------------------------------------------------------------*/ /* EXTERNAL LATCHED INTERRUPTS */ /*-------------------------------------------------------------------------*/ #define LIR0 BYTE_AT(0xFFFF8101) /* Latched Interrupt 0/1 register */ #define LIR1 BYTE_AT(0xFFFF8103) /* Latched Interrupt 2/3 register */ #define LIR2 BYTE_AT(0xFFFF8105) /* Latched Interrupt 4/5 register */ #define LIR3 BYTE_AT(0xFFFF8107) /* Latched Interrupt 6/7 register */ /*-------------------------------------------------------------------------*/ /* I2C */ /*-------------------------------------------------------------------------*/ #define SDAT BYTE_AT(0xFFFF8201) /* I2C Data Register */ #define SADR BYTE_AT(0xFFFF8203) /* I2C Address Register */ #define SSTA BYTE_AT(0xFFFF8205) /* I2C Status Register */ #define SCON BYTE_AT(0xFFFF8207) /* I2C Control Register */ /*-------------------------------------------------------------------------*/ /* TIMERS */ /*-------------------------------------------------------------------------*/ #define T0CR WORD_AT(0xFFFF8300) /* Timer 0 control register */ #define T0RR WORD_AT(0xFFFF8302) /* Timer 0 reload register */ #define T0 WORD_AT(0xFFFF8304) /* Timer 0 register */ #define T0C0 WORD_AT(0xFFFF8306) /* Timer 0 channel 0 register */ #define T0C1 WORD_AT(0xFFFF8308) /* Timer 0 channel 1 register */ #define T0C2 WORD_AT(0xFFFF830A) /* Timer 0 channel 2 register */ #define T0SR BYTE_AT(0xFFFF830D) /* Timer 0 status register */ #define T0PR BYTE_AT(0xFFFF830F) /* Timer 0 prescaler reload reg. */ #define #define #define #define #define #define #define #define T1CR T1RR T1 T1C0 T1C1 T1C2 T1SR T1PR WORD_AT(0xFFFF8310) WORD_AT(0xFFFF8312) WORD_AT(0xFFFF8314) WORD_AT(0xFFFF8316) WORD_AT(0xFFFF8318) WORD_AT(0xFFFF831A) BYTE_AT(0xFFFF831D) BYTE_AT(0xFFFF831F) /* /* /* /* /* /* /* /* Timer Timer Timer Timer Timer Timer Timer Timer 1 1 1 1 1 1 1 1 control register reload register register channel 0 register channel 1 register channel 2 register status register prescaler reload reg. */ */ */ */ */ */ */ */
/*-------------------------------------------------------------------------*/ /* WATCHDOG */ /*-------------------------------------------------------------------------*/ #define WDTIM BYTE_AT(0xFFFF8401) /* Watchdog Timer Register */ #define WDCON BYTE_AT(0xFFFF8403) /* Watchdog Control Register */
36
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
/*-------------------------------------------------------------------------*/ /* PORT REGISTERS */ /*-------------------------------------------------------------------------*/ #define PCON BYTE_AT(0xFFFF8503) /* P port control register */ #define PRL BYTE_AT(0xFFFF8505) /* P port port latch LSB */ #define PPL BYTE_AT(0xFFFF8507) /* P port port pin LSB */ #define PRH BYTE_AT(0xFFFF8509) /* P port port latch MSB */ #define PPH BYTE_AT(0xFFFF850B) /* P port port pin MSB */ #define SPCON BYTE_AT(0xFFFF8109) /* SP port control register */ #define SPR BYTE_AT(0xFFFF810B) /* SP port latch */ #define SPP BYTE_AT(0xFFFF810D) /* SP port pin */ /*-------------------------------------------------------------------------*/ /* UART */ /*-------------------------------------------------------------------------*/ #define SBUF0 BYTE_AT(0xFFFF8601) /* UART0 transmit/receive reg. */ #define SCON0 (*(SCONX_TYPE*) 0xFFFF8603) /* UART0 control register */ #define SBUF1 BYTE_AT(0xFFFF8605) /* UART1 transmit/receive reg. */ #define SCON1 (*(SCONX_TYPE*) 0xFFFF8607) /* UART1 control register */ #define BREGL #define BREGH #define BCON BYTE_AT(0xFFFF860B) BYTE_AT(0xFFFF860D) BYTE_AT(0xFFFF860F) /* UART baud rate register LSB /* UART baud rate register MSB /* UART baud rate control reg. */ */ */
/*-------------------------------------------------------------------------*/ /* PERIPHERAL INTERRUPT REGISTERS */ /*-------------------------------------------------------------------------*/ #define PICR0 BYTE_AT(0xFFFF8701) /* Timer interrupt register */ #define PICR1 BYTE_AT(0xFFFF8703) /* UART0 interrupt register */ #define PICR2 BYTE_AT(0xFFFF8705) /* UART1 interrupt register */ #define PICR3 BYTE_AT(0xFFFF8707) /* I2C/ADC interrupt register */ /*-------------------------------------------------------------------------*/ /* PULSE WIDTH MODULATION REGISTER */ /*-------------------------------------------------------------------------*/ #define PWMP BYTE_AT(0xFFFF8801) /* PWM prescaler register */ #define PWM0 BYTE_AT(0xFFFF8803) /* PWM0 data register */ #define PWM1 BYTE_AT(0xFFFF8805) /* PWM1 data register */ /*-------------------------------------------------------------------------*/ /* ADC REGISTER */ /*-------------------------------------------------------------------------*/ #define ADCON BYTE_AT(0xFFFF8807) /* ADC control register */ #define ADCDAT BYTE_AT(0xFFFF8809) /* ADC data register */ /*-------------------------------------------------------------------------*/ /* CHIP SELECT REGISTERS */ /*-------------------------------------------------------------------------*/ #define CS0N WORD_AT(0xFFFF8A00) /* chip select 0 control register */ #define CS1N WORD_AT(0xFFFF8A02) /* chip select 1 control register */ #define CS2N WORD_AT(0xFFFF8A04) /* chip select 2 control register */ #define CS3N WORD_AT(0xFFFF8A06) /* chip select 3 control register */ #define CS4N WORD_AT(0xFFFF8A08) /* chip select 4 control register */ #define CS5N WORD_AT(0xFFFF8A0A) /* chip select 5 control register */ #define CS6N WORD_AT(0xFFFF8A0C) /* chip select 6 control register */ #define CSBTN WORD_AT(0xFFFF8A0E) /* chip select boot control register */
37
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
APPENDIX VIII EXAMPLE.C
/***************************************************************************/ /* Acronym : I2C Inter IC bus */ /* Name of module : EXAMPLE.C */ /* Scope : Application software */ /* 12nc : xxxx xxx xxxx.x */ /* Creation date : 1994-10-08 */ /* Program language : C */ /* Name : P.H. Seerden */ /* */ /* */ /* (C) Copyright 1994 Philips Semiconductors B.V. */ /* Product Concept & Application Laboratory Eindhoven (PCALE) */ /* Eindhoven - The Netherlands */ /* */ /* All rights are reserved. Reproduction in whole or in part is */ /* prohibited without the written consent of the copyright owner. */ /* */ /***************************************************************************/ /* */ /* Description: */ /* */ /* IC driver test, for P90CL301 */ /* */ /* Runs on MICROCORE 5 and IC evaluation board type OM1016 */ /* */ /* - Read the time from the real time clock chip PCF8583. */ /* - Displays the time on LCD module PCF8577 and LED module SAA1064. */ /* - Reads keys from I/O expander PCF8574. */ /* - Depending of pushed keys send tone to loudspeaker PCD3312. */ /* */ /***************************************************************************/ /* */ /* History: */ /* */ /* 92-12-10 P.H. Seerden Initial version */ /* */ /* */ /***************************************************************************/ #include #include "i2cexprt.h"
#define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define
PCF8574_WR PCF8574_RD PCD3312_WR SAA1064_WR SAA1064_RD PCF8577_WR PCF8583_WR PCF8583_RD LCDA LCDB LCDC LCDD LCDE LCDF LCDG LCDDP LEDA LEDB LEDC LEDD LEDE LEDF LEDG LEDDP
0x7E 0x7F 0x4A 0x76 0x77 0x74 0xA2 0xA3 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01 0x04 0x08 0x40 0x20 0x10 0x01 0x02 0x80
/* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /*
i2c i2c i2c i2c i2c i2c i2c i2c LCD LCD LCD LCD LCD LCD LCD LCD LED LED LED LED LED LED LED LED
address address address address address address address address segment segment segment segment segment segment segment segment segment segment segment segment segment segment segment segment
I/O poort write I/O poort read DTMF 7 segm. Led 7 segm. Led 7 segm. LCD Clock Clock a b c d e f g dp a b c d e f g dp
*/ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */
38
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
/* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* 0 1 2 3 4 5 6 7 8 9 A blank d e */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */
const BYTE lcdTbl[] = { LCDA+LCDB+LCDC+LCDD+LCDE+LCDF, LCDB+LCDC, LCDA+LCDB+LCDG+LCDD+LCDE, LCDA+LCDB+LCDG+LCDD+LCDC, LCDB+LCDG+LCDF+LCDC, LCDA+LCDF+LCDG+LCDC+LCDD, LCDA+LCDF+LCDG+LCDC+LCDD+LCDE, LCDA+LCDB+LCDC, LCDA+LCDB+LCDC+LCDD+LCDE+LCDF+LCDG, LCDA+LCDB+LCDC+LCDD+LCDF+LCDG, LCDA+LCDB+LCDC+LCDE+LCDF+LCDG, 0, LCDA, LCDB+LCDC+LCDD+LCDE+LCDG, LCDG, LCDD, LCDDP }; const BYTE ledTbl[] = { LEDA+LEDB+LEDC+LEDD+LEDE+LEDF, LEDB+LEDC, LEDA+LEDB+LEDG+LEDD+LEDE, LEDA+LEDB+LEDG+LEDD+LEDC, LEDB+LEDG+LEDF+LEDC, LEDA+LEDF+LEDG+LEDC+LEDD, LEDA+LEDF+LEDG+LEDC+LEDD+LEDE, LEDA+LEDB+LEDC, LEDA+LEDB+LEDC+LEDD+LEDE+LEDF+LEDG, LEDA+LEDB+LEDC+LEDD+LEDF+LEDG, LEDA+LEDB+LEDC+LEDE+LEDF+LEDG, 0, LEDA, LEDB+LEDC+LEDD+LEDE+LEDG, LEDG, LEDD, LEDDP };
0 1 2 3 4 5 6 7 8 9 A blank d e
static static static static static static static static static static static
BYTE BYTE BYTE BYTE BYTE
ledBuf[5]; lcdBuf[5]; rtcBuf[4]; iopBuf[1]; sndBuf[1]; rtcMsg1; rtcMsg2; iopMsg; sndMsg; ledMsg; lcdMsg;
I2C_MESSAGE I2C_MESSAGE I2C_MESSAGE I2C_MESSAGE I2C_MESSAGE I2C_MESSAGE
39
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
static void Init(void) { void **ptr; #define VECTOR_BASE
0x80000
/* start of vector table on mcore 5
*/
ptr = (void *) (VECTOR_BASE + (4 * (56 + 2))); *ptr = (void *) I2C_Interrupt; I2C_InitializeMaster(); I2C_InstallInterrupt(2); ledMsg.address = SAA1064_WR; ledMsg.nrBytes = 2; ledMsg.buf = ledBuf; ledBuf[0] = 0; ledBuf[1] = 0x47; I2C_Write(&ledMsg); ledMsg.nrBytes = 5; rtcBuf[0] = 2; rtcBuf[1] = 0x00; rtcBuf[2] = 0x59; rtcBuf[3] = 0x23; rtcMsg1.address = PCF8583_WR; rtcMsg1.nrBytes = 4; rtcMsg1.buf = rtcBuf; I2C_Write(&rtcMsg1); rtcBuf[0] = 2; rtcMsg1.nrBytes rtcMsg1.buf rtcMsg2.address rtcMsg2.nrBytes rtcMsg2.buf = = = = = 1; rtcBuf; PCF8583_RD; 3; rtcBuf; /* Interrupt level 2 */
/* led brightness /* /* /* /* sub address seconds minutes hours
*/ */ */ */ */
/* set clock /* sub address
*/ */
iopMsg.address = PCF8574_RD; iopMsg.buf = iopBuf; iopMsg.nrBytes = 1; sndMsg.address = PCD3312_WR; sndMsg.buf = sndBuf; sndMsg.nrBytes = 1; lcdMsg.address = PCF8577_WR; lcdMsg.buf = lcdBuf; lcdMsg.nrBytes = 5; } static void HandleKeys(void) { I2C_Read(&iopMsg); switch ((iopBuf[0] ^ 0xFF) & 0x0F) { case 0 : sndBuf[0] = 0x01; break; case 1 : sndBuf[0] = 0x30; break; case 2 : sndBuf[0] = 0x31; break; case 3 : sndBuf[0] = 0x32; break; case 4 : sndBuf[0] = 0x33; break; case 5 : sndBuf[0] = 0x34; break; case 6 : sndBuf[0] = 0x35; break; case 7 : sndBuf[0] = 0x36; break; case 8 : sndBuf[0] = 0x37; break; case 9 : sndBuf[0] = 0x38; break; case 10 : sndBuf[0] = 0x39; break; case 11 : sndBuf[0] = 0x3A; break; case 12 : sndBuf[0] = 0x29; break; case 13 : sndBuf[0] = 0x3B; break; case 14 : sndBuf[0] = 0x3C; break; case 15 : sndBuf[0] = 0x3D; break; } I2C_Write(&sndMsg); }
40
Philips Semiconductors www..com
P90CL301 I2C driver routines
Application Note AN94078
void main(void) { BYTE oldseconds = 0; Init(); while (1) { HandleKeys(); rtcBuf[0] = 2; I2C_WriteRepRead(&rtcMsg1, &rtcMsg2); if (rtcBuf[0] != oldseconds) { oldseconds = rtcBuf[0]; /* sub address */
/* check if one second is passed */
lcdBuf[0] = 0; if (oldseconds & 1) lcdBuf[1] = lcdTbl[rtcBuf[2] >> 4]; else lcdBuf[1] = lcdTbl[rtcBuf[2] >> 4] | LCDDP; lcdBuf[2] = lcdTbl[rtcBuf[2] & 0x0F]; lcdBuf[3] = lcdTbl[rtcBuf[1] >> 4]; lcdBuf[4] = lcdTbl[rtcBuf[1] & 0x0F]; I2C_Write(&lcdMsg); ledBuf[0] = 1; ledBuf[1] = 2; ledBuf[2] = ledTbl[rtcBuf[0] >> 4]; ledBuf[3] = ledTbl[rtcBuf[0] & 0x0F]; ledBuf[4] = 2; I2C_Write(&ledMsg); } } }
41